Associating Format Objects With Document Pages
Your application is responsible for managing the correspondence between format objects and individual pages in a document. For example, a user may create a document that consists of three pages. Through the Custom Page Setup dialog box, you can allow a user to specify that pages 1 and 2 use portrait orientation and page 3 uses landscape orientation. In this example, you need to store information that pages 1 and 2 use the default format, while page 3 uses a unique format object.When a user saves a document containing multiple format objects, you need to save format collection information and then flatten the document's job object. In addition, when a user opens a document containing multiple format objects, you need to unflatten its corresponding job object and retrieve the format collection information. Flattening and unflattening a document's corresponding job object is discussed in the chapter "Core Printing Features" in this book.
There are several methods you can use to store formatting information. A common method, shown in this section, is to save the correspondence between format objects and pages in the format collection. Listing 3-19 shows a function that performs this task.
Listing 3-19 Saving the correspondence between format objects and document pages in a format collection
OSErr MySaveFormatRefs(MyDocumentPtr myDocument) { OSErr err = noErr; Handle theFormatIdxList; Collection fmtCollection; gxFormat defaultFmt; /* Create a handle containing all of the format object indices. */ if (myDocument->numPages > 0) { /* Obtain the format collection. If you have already have a document page-to-format object correspondence item stored, remove it. */ defaultFmt = GXGetJobFormat(myDocument->documentJob, 1); fmtCollection = GXGetFormatCollection(defaultFmt); if (fmtCollection != nil) RemoveCollectionItem(fmtCollection, kMyFormatInfoType, printingTagID); /* Create a list of document page-to-format object correspondences for the current document. If there are no errors, add the item to the format collection for later retrieval. */ err = MyCreateFormatIndexList(myDocument, &theFormatIdxList); if (err == noErr) { HLock(theFormatIdxList); err = AddCollectionItem(fmtCollection, kMyFormatInfoType, printingTagID, GetHandleSize(theFormatIdxList), *theFormatIdxList); DisposHandle(theFormatIdxList); } } return err; }The MyCreateFormatIndexList function stores the index of each page's format object in a handle. The index of the format object for page 1 goes in the first long word oftheFormatIdxList
handle. The index of the next page's format object goes in the next long word, and so on. The handle is created and returned to the caller. Listing 3-20 shows the MyCreateFormatIndexList function.Listing 3-20 Filling the handle
OSErr MyCreateFormatIndexList(MyDocumentPtr myDocument, Handle *theFormatIdxList) { OSErr err; long fmtIdx, pg, *idxList; gxFormat curFormat; /* Create a handle large enough to hold all of our entries. This example uses NewHandleClear so that all of our indices are initialized to 0 (an invalid format index). This application stores a nil format reference for each page which uses the default format. This allows us to indicate these "nil references" by an index of 0 in our resource. */ *theFormatIdxList = NewHandleClear(sizeof(long) * (myDocument->numPages)); err = MemError(); /* If there aren't any errors, go through each format object. If the format object is used by any pages of the document, store the format object's index in those page entries of theFormatIdxList. Skip format object #1, because that's the default format. */ if (err == noErr) { HLock(*theFormatIdxList); idxList = (long *) **theFormatIdxList; for (fmtIdx = 2; fmtIdx <= GXCountJobFormats(myDocument->documentJob); fmtIdx++) { curFormat = GXGetJobFormat(myDocument->documentJob, fmtIdx); for (pg = 1; pg <= myDocument->numPages; pg++) if (myDocument->pageFormat[pg -1] == curFormat) idxList[pg -1] = fmtIdx; } HUnlock(*theFormatIdxList); } return err; }Listing 3-21 shows how to retrieve format object correspondence from a format collection when a user opens a document containing multiple format objects. This function associates new format object references with a document, based upon the format object indices that are saved with the document. The function is called when a document is opened. The format object references are stored in the passedMyDocumentRec
structure.Listing 3-21 Retrieving the correspondence between document pages and format objects from a format collection
OSErr MyAdjustFormats(MyDocumentPtr myDocument) { OSErr err = noErr; Handle theFormatIdxList = nil; gxFormat theFormat, defaultFmt; long pg, numPages, fmtIdx, *idxList, idx, listSize, attribs; Collection fmtCollection; /* Get the format collection, and search for one of the document page-to-format object correspondence items. */ defaultFmt = GXGetJobFormat(myDocument->documentJob, 1); fmtCollection = GXGetFormatCollection(defaultFmt); /* Load the item containing the correspondences. First, determine if the item exists. Next, create a handle to hold the item, and retrieve it. Because there is one long-word entry for each page of the document, determine the number of pages in the document. */ err = GetCollectionItemInfo(fmtCollection, kMyFormatInfoType, gxPrintingTagID, &idx, &listSize, &attribs); if (err == noErr) theFormatIdxList = NewHandle(listSize); if (theFormatIdxList != nil) { HLock(theFormatIdxList); err = GetCollectionItem(fmtCollection, kMyFormatInfoType, gxPrintingTagID, nil, *theFormatIdxList); numPages = listSize / sizeof(long); /* Loop through each saved index. In this example, the first index is for page 1, the second is for page 2, and so on. Call the GXGetJobFormat function for each saved index. Store the format references as they are processed. When finished, throw away the handle. */ idxList = (long *) *theFormatIdxList; for (pg = 1; pg <= numPages; pg++) { fmtIdx = idxList[pg -1]; if (fmtIdx != nil) theFormat = GXGetJobFormat(myDocument->documentJob, fmtIdx); else theFormat = nil; myDocument->pageFormat[pg -1] = theFormat; } DisposHandle(theFormatIdxList); } return err; }
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help